Hi 大家,昨天我們掌握了 Rust 的變數和資料型別,今天我們來看看如何透過函式來組織程式碼,以及掌握程式的流程控制。函式是程式模組化的基礎,而流程控制則決定了程式的執行邏輯。
在 Rust 中,使用 fn
關鍵字定義函式:
fn main() {
println!("Hello, world!");
// 呼叫自定義函式
say_hello();
greet("小明");
}
fn say_hello() {
println!("你好!");
}
fn greet(name: &str) {
println!("你好,{}!", name);
}
函式參數必須指定型別:
fn main() {
let result = add(5, 3);
println!("5 + 3 = {}", result);
let info = create_user_info("張小華", 25);
println!("{}", info);
}
fn add(x: i32, y: i32) -> i32 {
x + y // 注意:沒有分號,這是回傳值
}
fn create_user_info(name: &str, age: u32) -> String {
format!("用戶:{},年齡:{} 歲", name, age)
}
Rust 函式的回傳值有兩種方式:
fn main() {
println!("明確回傳: {}", explicit_return(10));
println!("隱含回傳: {}", implicit_return(10));
print_number(42); // 無回傳值的函式
}
// 明確使用 return 關鍵字
fn explicit_return(x: i32) -> i32 {
if x > 0 {
return x * 2; // 提前回傳
}
0
}
// 隱含回傳(最後一個表達式)
fn implicit_return(x: i32) -> i32 {
x * 3 // 沒有分號
}
// 無回傳值(單位型別 ())
fn print_number(x: i32) {
println!("數字是: {}", x);
}
fn main() {
let numbers = vec![1, 2, 3, 4, 5];
let sum = apply_operation(&numbers, add_one);
println!("加一後的總和: {}", sum);
let sum2 = apply_operation(&numbers, |x| x * 2); // 閉包
println!("乘二後的總和: {}", sum2);
}
fn add_one(x: i32) -> i32 {
x + 1
}
fn apply_operation<F>(numbers: &[i32], operation: F) -> i32
where
F: Fn(i32) -> i32
{
numbers.iter().map(|&x| operation(x)).sum()
}
fn main() {
let number = 6;
// 基本 if 表達式
if number % 4 == 0 {
println!("數字可以被 4 整除");
} else if number % 3 == 0 {
println!("數字可以被 3 整除");
} else if number % 2 == 0 {
println!("數字可以被 2 整除");
} else {
println!("數字無法被 4、3 或 2 整除");
}
// if 作為表達式
let condition = true;
let number = if condition { 5 } else { 6 };
println!("條件決定的數字: {}", number);
// 複雜條件判斷
let age = 20;
let is_student = true;
let ticket_price = if age < 12 {
"兒童票:150元"
} else if age >= 65 {
"敬老票:200元"
} else if is_student {
"學生票:250元"
} else {
"全票:300元"
};
println!("票價:{}", ticket_price);
}
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2; // 回傳值
}
println!("計數: {}", counter);
};
println!("迴圈結果: {}", result);
}
fn main() {
let mut number = 3;
while number != 0 {
println!("{}!", number);
number -= 1;
}
println!("發射!");
// 使用 while 遍歷集合(不推薦)
let a = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("陣列值: {}", a[index]);
index += 1;
}
}
fn main() {
// 遍歷陣列(推薦方式)
let a = [10, 20, 30, 40, 50];
for element in a {
println!("值: {}", element);
}
// 使用範圍
for number in (1..4).rev() {
println!("{}!", number);
}
println!("發射!");
// 帶索引的遍歷
let fruits = ["蘋果", "香蕉", "橘子"];
for (index, fruit) in fruits.iter().enumerate() {
println!("第 {} 個水果: {}", index + 1, fruit);
}
// 巢狀迴圈與標籤
'outer: for i in 0..3 {
for j in 0..3 {
if i == 1 && j == 1 {
break 'outer; // 跳出外層迴圈
}
println!("i: {}, j: {}", i, j);
}
}
}
fn main() {
let dice_roll = 6;
match dice_roll {
1 => println!("得到 1 點!"),
2 | 3 => println!("得到 2 或 3 點!"), // 多個值
4..=6 => println!("得到 4 到 6 點!"), // 範圍
_ => println!("其他點數"), // 預設情況
}
// match 作為表達式
let message = match dice_roll {
1 => "很小",
2..=3 => "小",
4..=5 => "中",
6 => "大",
_ => "未知",
};
println!("骰子結果: {}", message);
}
fn main() {
// 匹配元組
let point = (2, 3);
match point {
(0, 0) => println!("原點"),
(0, y) => println!("在 Y 軸上,y = {}", y),
(x, 0) => println!("在 X 軸上,x = {}", x),
(x, y) => println!("座標: ({}, {})", x, y),
}
// 條件守衛
let number = Some(4);
match number {
Some(x) if x < 5 => println!("小於 5: {}", x),
Some(x) => println!("大於等於 5: {}", x),
None => println!("沒有值"),
}
// 綁定變數
let age = 25;
match age {
n @ 13..=19 => println!("青少年,年齡: {}", n),
n @ 20..=59 => println!("成年人,年齡: {}", n),
n if n >= 60 => println!("長者,年齡: {}", n),
_ => println!("兒童"),
}
}
讓我們建立一個綜合運用今天所學概念的猜數字遊戲:
use std::io;
use std::cmp::Ordering;
fn main() {
println!("=== 猜數字遊戲 ===");
let secret_number = generate_secret_number();
let mut attempts = 0;
let max_attempts = 7;
loop {
attempts += 1;
println!("\n第 {} 次嘗試(剩餘 {} 次)", attempts, max_attempts - attempts + 1);
let guess = get_user_input();
match check_guess(guess, secret_number) {
GameResult::TooLow => {
println!("太小了!");
if attempts >= max_attempts {
println!("很可惜,答案是 {}!", secret_number);
break;
}
}
GameResult::TooHigh => {
println!("太大了!");
if attempts >= max_attempts {
println!("很可惜,答案是 {}!", secret_number);
break;
}
}
GameResult::Correct => {
println!("🎉 恭喜!你猜對了!");
let performance = evaluate_performance(attempts);
println!("你用了 {} 次就猜中,{}", attempts, performance);
break;
}
}
if attempts >= max_attempts {
break;
}
}
if play_again() {
main(); // 重新開始遊戲
} else {
println!("感謝遊玩!");
}
}
// 列舉定義遊戲結果
#[derive(Debug)]
enum GameResult {
TooLow,
TooHigh,
Correct,
}
fn generate_secret_number() -> u32 {
// 簡單的偽隨機數生成(實際專案中應使用 rand crate)
use std::time::{SystemTime, UNIX_EPOCH};
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("時間錯誤")
.as_secs();
((timestamp % 100) as u32) + 1
}
fn get_user_input() -> u32 {
loop {
println!("請輸入你的猜測(1-100):");
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("讀取輸入失敗");
match input.trim().parse() {
Ok(num) if num >= 1 && num <= 100 => return num,
Ok(_) => println!("請輸入 1 到 100 之間的數字!"),
Err(_) => println!("請輸入有效的數字!"),
}
}
}
fn check_guess(guess: u32, secret: u32) -> GameResult {
match guess.cmp(&secret) {
Ordering::Less => GameResult::TooLow,
Ordering::Greater => GameResult::TooHigh,
Ordering::Equal => GameResult::Correct,
}
}
fn evaluate_performance(attempts: u32) -> &'static str {
match attempts {
1 => "天才!一次就中!",
2..=3 => "太厲害了!",
4..=5 => "很不錯!",
6..=7 => "還不錯!",
_ => "需要多練習!",
}
}
fn play_again() -> bool {
loop {
println!("想再玩一次嗎?(y/n)");
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("讀取輸入失敗");
match input.trim().to_lowercase().as_str() {
"y" | "yes" | "是" => return true,
"n" | "no" | "否" => return false,
_ => println!("請輸入 y 或 n"),
}
}
}
今天我們學習了 Rust 的函式系統和程式流程控制,重點包括:
明天我們將學習 Rust 的所有權系統,這是 Rust 實現記憶體安全的核心機制。